package inglar.autotc.server;

import inglar.autotc.shared.Values;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

/**
 * A collection of convenience functions.
 * @author Lee
 */
public class Host {

	private Host() {
		/* 
		 * Static access only! 
		 */
	}
	
	/**
	 * Get the current time as a string, formatted by {@link Values#FMT_TIMESTAMP}.
	 * @return the timestamp
	 */
	public static String timeStamp() {
		SimpleDateFormat fmt = new SimpleDateFormat(Values.FMT_TIMESTAMP);
		return fmt.format(new Date());
	}

	/**
	 * Prints a thrown instance's class name and error message (which may be null).
	 * @param caught a thrown {@link Throwable} instance
	 * @return 
	 */
	public static String throwableDump(Throwable caught) {
		if(caught == null) return null;
		return caught.getClass().getName() + " (" + caught.getMessage() + ")";
	}
	
	/**
	 * Print a message to standard error and exit.
	 * @param msg the message
	 */
	public static void fatal(String msg) {
		System.err.println(msg);
		System.exit(1);
	}

	/**
	 * Print a message to standard error using a thrown {@link Throwable} instance and exit.
	 * @param caught
	 */
	public static void fatal(Throwable caught) {
		if(caught != null) {
			System.err.println(caught.getMessage());
			caught.printStackTrace();
		}
		System.exit(1);
	}
	
	
	@SuppressWarnings("deprecation")
	private static String getLocalDir(HttpServletRequest req) {
		String _t = req.getRealPath("./");
//		throw new RuntimeException("_t is {" + _t + "}");
		return _t.substring(0, _t.indexOf("webapp"));
	}
	
	/**
	 * Runs Linux commands.
	 * @param cmd the command to be run, does not allow $VARIABLES
	 * @return the 
	 * @throws RuntimeException
	 */
	public static String exec(String cmd) throws RuntimeException {
		if((cmd == null) || cmd.isEmpty()) throw new IllegalArgumentException("Argument String must be nonempty");
		
		String retval = "", errstr = "", temp = "";
		
		try {
			Runtime rt = Runtime.getRuntime();
			Process proc = rt.exec(cmd);
			BufferedReader stdin = new BufferedReader(new InputStreamReader(proc.getInputStream()));
			BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
			while ((temp = stdin.readLine()) != null) retval += temp + "\n";
	        while ((temp = stdError.readLine()) != null) errstr += temp + "\n";
	        if(!errstr.isEmpty()) throw new RuntimeException("Caught on error stream while running '" + cmd + "' : " + errstr);
		} catch(Exception e) {
			throw new RuntimeException(e.getMessage());
		}
		
		return retval.trim();
	}
	
	/**
	 * Runs Linux scripts as a file. Passing an {@link HttpServletRequest} 
	 * object allows this method to write the script file into the servlet 
	 * container's local address.
	 * 
	 * @deprecated Using {@link Host#exec(String)} is recommended.
	 * 
	 * @param cmd the scripts to be run, allows $VARIABLES
	 * 
	 * @param req the {@link HttpServletRequest} instance
	 * 
	 * @return the scripts' command-line outputs
	 * 
	 * @throws RuntimeException
	 */
	public static String scriptase(String cmd, HttpServletRequest req) throws RuntimeException {
		if(cmd.isEmpty() || (cmd == null)) return "";
		//throw new IllegalArgumentException("Argument String must be nonempty");
		
		String retval = "";
		
		// sets a file unique to the current user's session
		String filepath = getLocalDir(req) + "autotc_rpc_" + req.getSession().getId() 
				+ new Random().nextInt(); // the random int part ensures different files for two consecutive rpcs
		
		try {
			File fptr = new File(filepath);
			fptr.createNewFile();
			exec("chmod a+x " + filepath); // make the file executable
			if(!fptr.canExecute()) throw new Exception("Cannot execute file '" + filepath + "'");
			FileWriter fwrite = new FileWriter(fptr);
			fwrite.write(cmd);
			fwrite.close();
			retval += exec(filepath);
			fptr.delete();
		} catch(IOException ioe) {
			throw new RuntimeException(ioe.getMessage());
		} catch(Exception e) {
			throw new RuntimeException(e.getMessage());
		}
		
		return retval;
	}
	
	public static String getCmd() throws Exception {
		String retval = null;
		retval = System.getenv(Values.ENVNAME_SYS_HOME_DIR);
		if(retval == null) throw new Exception("Cannot find environment variable " + Values.ENVNAME_SYS_HOME_DIR);
		retval = retval.trim() + "/" + Values.DAEMON_FILE_NAME;
		if(! (new File(retval.trim()).exists())) throw new Exception("Cannot find file " + retval.trim());
		return retval;
	}
	
	/**
	 * Gets the JAVA_HOME environment variable.
	 * @return 
	 * the path of the JAVA_HOME environment variable, 
	 * or <code>null</code> if the environment variable is not set
	 */
	public static String getJavaHome() {
		String retval = null;
		try {
//			retval = System.getenv("JAVA_HOME");
			retval = System.getProperty("java.home", retval);
		} catch (Throwable caught) {
			
		}
		if(retval == null) {
//			fatal("Cannot retrieve java.home property");
			return retval;
		} else {
			return retval;
		}
	}
	
	public static void main(String[] args) {
		System.out.println(Host.class.getName());
		System.out.println("null".equals(null + ""));
	}

	public static String out(String msg) {
		System.out.println(msg);
		return msg;
	}

	public static String err(String msg) {
		System.err.println(msg);
		return msg;
	}

	public static String run(String string) throws Exception {
		String jar = "java -jar " + Host.getCmd() + " ";
		String retval = Host.exec(jar + string);
		return retval;
	}

}
